#ifndef TYPE_TRAITS_H
#define TYPE_TRAITS_H
#include <type_traits>
/**
 * @brief Trait to check if a type is a lambda function.
 * 
 * This trait struct inherits from `std::integral_constant`, providing a compile-time constant boolean
 * value `is_lambda::value` that is `true` if the type `T` is a lambda function, and `false` otherwise.
 * It leverages the fact that lambda functions are unique, unnamed (anonymous) classes in C++. This trait
 * checks if a type is a class (`std::is_class_v<T>`) and not the same as its decayed type
 * (`!std::is_same_v<T, std::decay_t<T>>`). The decayed type of a lambda function is a function pointer
 * type when the lambda does not capture any variables, thus making this trait effective for distinguishing
 * lambda functions from other types.
 * 
 * @tparam T The type to be checked.
 * 
 * Usage example:
 * ```
 * auto lambda = [](){ return 42; };
 * std::cout << is_lambda<decltype(lambda)>::value << std::endl; // Output: 1 (true)
 * 
 * int x = 0;
 * std::cout << is_lambda<decltype(x)>::value << std::endl; // Output: 0 (false)
 * ```
 * 
 * @note This trait may not accurately identify lambdas with captures as different from other classes,
 * because it primarily checks if `T` is a class type and different from its decay type. Lambdas with
 * captures are still classes, but their type is not decayable to a function pointer, hence they are
 * identified correctly. However, this distinction does not extend to differentiating between lambdas
 * and other class types without additional context.
 */
template <typename T>
struct is_lambda : 
    std::integral_constant<
        bool, 
        std::is_class_v<T> && !std::is_same_v<T, std::decay_t<T>>
    > 
{};


#endif // TYPE_TRAITS_H